// SPDX-FileCopyrightText: Adam Evyčędo
//
// SPDX-License-Identifier: AGPL-3.0-or-later

package traffic

import (
	"apiote.xyz/p/szczanieckiej/config"
	"apiote.xyz/p/szczanieckiej/transformers"

	"encoding/csv"
	"fmt"
	"io"
	"net/http"
	"regexp"
	"strings"
	"time"

	"golang.org/x/text/transform"
)

type HtmlSelector struct {
	tag   string
	id    string
	class string
}

type PoznanZtm struct {
	client http.Client
}

func (PoznanZtm) getTimezone() *time.Location {
	l, _ := time.LoadLocation("Europe/Warsaw")
	return l
}

func (z PoznanZtm) ConvertVehicles() ([]Vehicle, error) {
	vehicles := []Vehicle{}

	url := "https://ztm.poznan.pl/pl/dla-deweloperow/getGtfsRtFile/?file=vehicle_dictionary.csv"
	response, err := z.client.Get(url)
	if err != nil {
		return vehicles, fmt.Errorf("ConvertVehicles: cannot GET ‘%s’: %w", url, err)
	}

	r := csv.NewReader(response.Body)
	r.Comma = ','
	header, err := r.Read()
	if err != nil {
		fmt.Println("Header read error")
		return vehicles, err
	}
	fields := map[string]int{}
	for i, headerField := range header {
		fields[headerField] = i
	}

	for {
		record, err := r.Read()
		if err == io.EOF {
			break
		}
		if err != nil {
			return vehicles, err
		}

		var capabilites uint16 = 0

		if record[fields["ramp"]] == "1" {
			capabilites |= 0b0001
		}
		if record[fields["hf_lf_le"]] == "1" {
			capabilites |= 0b0010
		}
		if record[fields["hf_lf_le"]] == "2" {
			capabilites |= 0b0001_0000_0000
		}
		if record[fields["air_conditioner"]] == "1" {
			capabilites |= 0b0100
		}
		if record[fields["place_for_transp_bicycles"]] == "1" {
			capabilites |= 0b1000
		}
		if record[fields["voice_announcement_sys"]] == "1" {
			capabilites |= 0b0001_0000
		}
		if record[fields["ticket_machine"]] == "1" {
			capabilites |= 0b0010_0000
		}
		if record[fields["ticket_sales_by_the_driver"]] == "1" {
			capabilites |= 0b0100_0000
		}
		if record[fields["usb_charger"]] == "1" {
			capabilites |= 0b1000_0000
		}

		vehicles = append(vehicles, Vehicle{
			Id:           record[0],
			Capabilities: capabilites,
		})

	}
	return vehicles, nil
}

func (z PoznanZtm) GetVersions(date time.Time, timezone *time.Location) ([]Version, error) {
	url := "https://www.ztm.poznan.pl/otwarte-dane/gtfsfiles/"
	response, err := z.client.Get(url)
	if err != nil {
		return []Version{}, fmt.Errorf("GetVersions: cannot GET ‘%s’: %w", url, err)
	}
	doc, err := io.ReadAll(response.Body)
	if err != nil {
		return []Version{}, fmt.Errorf("GetVersions: cannot read whole html: %w", err)
	}

	regex, err := regexp.Compile("[0-9]{8}_[0-9]{8}\\.zip")
	versionStrings := regex.FindAllString(string(doc), -1)
	versionsSet := map[string]struct{}{}
	for _, v := range versionStrings {
		versionsSet[v] = struct{}{}
	}

	versions := []Version{}
	for v := range versionsSet {
		validityString := strings.Replace(v, ".zip", "", 1)
		version, err := MakeVersionTimezone(validityString, timezone)
		if err != nil {
			return nil, err
		}
		version.Link = "https://ztm.poznan.pl/pl/dla-deweloperow/getGTFSFile/?file=" + v
		versions = append(versions, version)
	}
	return versions, nil
}

func (PoznanZtm) String() string {
	return "poznan_ztm"
}

func (PoznanZtm) RealtimeFeeds() map[RealtimeFeedType]string {
	return map[RealtimeFeedType]string{
		TRIP_UPDATES:      "https://ztm.poznan.pl/pl/dla-deweloperow/getGtfsRtFile/?file=feeds.pb",
		VEHICLE_POSITIONS: "https://ztm.poznan.pl/pl/dla-deweloperow/getGtfsRtFile/?file=feeds.pb",
	}
}

func (PoznanZtm) LuaUpdatesScript(config.Auth) string {
	return ""
}

func (PoznanZtm) Transformer() transform.Transformer {
	return transformers.TransformerPL
}

func (PoznanZtm) Name() string {
	return "Poznań ZTM"
}

func (PoznanZtm) Flags() FeedFlags {
	return FeedFlags{
		Headsign:     HeadsignTripHeadsing,
		StopIdFormat: "{{stop_code}}",
		StopName:     "{{stop_name}} [{{stop_code}}]",
		LineName:     "{{route_short_name}}",
	}
}

func (PoznanZtm) FeedPrepareZip(path string) error {
	return nil
}

func (PoznanZtm) QRInfo() (string, QRLocation, string) {
	return "www.peka.poznan.pl", QRLocationQuery, "przystanek"
}
